package cz.cvut.kadledav.paa.weight3sat.bo;

import java.util.List;

/**
 * User: David Kadlecek
 * Date: 30.12.13
 */
public class SolutionState {

    final private boolean[] evaluation;
    final private int weight;
    final private int variableWeightSum;
    final private int optCriteria;
    final private int numberOfUnsatisfiableClauses;
    final private Instance instance;


    private SolutionState(boolean[] evaluation, int weight, int numberOfUnsatisfiableClauses, Instance instance) {
        this.evaluation = evaluation;
        this.weight = weight;
        this.numberOfUnsatisfiableClauses = numberOfUnsatisfiableClauses;
        this.variableWeightSum = instance.getVariableWeightSum();
        this.instance = instance;
        this.optCriteria = (weight) - (numberOfUnsatisfiableClauses * instance.getVariableWeightSum());
//        this.optCriteria = -numberOfUnsatisfiableClauses;
    }

    public boolean[] getEvaluation() {
        return evaluation;
    }

    public int getWeight() {
        return weight;
    }

    public int getNumberOfUnsatisfiableClauses() {
        return numberOfUnsatisfiableClauses;
    }

    public int getVariableWeightSum() {
        return variableWeightSum;
    }

    public boolean isBetterThan(SolutionState other) {
        return optCriteria >= other.optCriteria;
    }

    public Instance getInstance() {
        return instance;
    }

    public static SolutionState createFromInstanceAndEvaluation(Instance instance, boolean[] evaluation) {
        int[] variablesWeight = instance.getVariablesWeight();
        List<Variable[]> clauses = instance.getClauses();
        int weight = 0;
        boolean[] evaluationNew = new boolean[evaluation.length];
        for (int i = 0; i < evaluationNew.length; i++) {
            evaluationNew[i]=evaluation[i];
            if (evaluationNew[i]) {
                weight += variablesWeight[i];
            }
        }
        int satisfiableClausules = 0;
        for (Variable[] clause : clauses) {
            Variable term1 = clause[0];
            Variable term2 = clause[1];
            Variable term3 = clause[2];
            if(term1.getValue(evaluationNew[term1.getIndex()]) || term2.getValue(evaluationNew[term2.getIndex()]) || term3.getValue(evaluationNew[term3.getIndex()])){
                satisfiableClausules++;
            };
        }
        return new SolutionState(evaluationNew, weight, clauses.size() - satisfiableClausules, instance);
    }

    public int getOptCriteria(){
        return optCriteria;
    }

}
